package cn.touna.jss.modules.third.dianhuabang.service.impl;

import cn.touna.jss.common.cache.HbaseComponent;
import cn.touna.jss.common.entity.CreditQueryRequest;
import cn.touna.jss.common.util.DateUtil;
import cn.touna.jss.common.util.DateUtils;
import cn.touna.jss.modules.callback.entity.DianHuaBangCallback;
import cn.touna.jss.modules.callback.entity.DianHuaBangCallbackExample;
import cn.touna.jss.modules.callback.mapper.DianHuaBangCallbackMapper;
import cn.touna.jss.modules.third.dianhuabang.entity.CallLogEntity;
import cn.touna.jss.modules.third.dianhuabang.entity.DianHuaBangRequestEntity;
import cn.touna.jss.modules.third.dianhuabang.entity.DianHuaBangResponseEntity;
import cn.touna.jss.modules.third.dianhuabang.service.IDianHuaBangService;
import cn.touna.jss.modules.third.dianhuabang.utils.GZipUtil;
import cn.touna.jss.common.util.HttpClientFactory;
import cn.touna.jss.modules.third.dianhuabang.utils.MobileUtil;
import cn.touna.jss.modules.third.dianhuabang.utils.TimestampUtil;
import cn.touna.risk.api.domain.Response;
import cn.touna.risk.api.exception.ServiceException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.*;

@Service
public class DianHuaBangServiceImpl implements IDianHuaBangService {

    public static final String DHB_RETRY_CODE = "-1";
    public static final String DHB_ERROR_CODE = "-2";
    public static final String DHB_OK_CODE = "200";

    private static final Logger LOG = LogManager.getLogger(DianHuaBangServiceImpl.class);

    @Autowired
    private DianHuaBangCallbackMapper dianHuaBangCallbackMapper;

    @Autowired
    private HbaseComponent hbaseComponent;

    @Override
    public Response callLogList(DianHuaBangRequestEntity request) {
        Response response = new Response();
        response.setCode(DHB_RETRY_CODE);
        response.setData(Collections.EMPTY_LIST);
        CreditQueryRequest creditQueryRequest = new CreditQueryRequest();
        creditQueryRequest.setMethod("JuXinLi.getAccessRawData");
        creditQueryRequest.setIdCard(request.getIdCard());
        creditQueryRequest.setMobile(request.getMobile());
        String cachedData = hbaseComponent.queryCacheData(creditQueryRequest);
        if (StringUtils.isEmpty(cachedData)) {
            return response;
        }
        try {
            List<CallLogEntity> callLogList = new ArrayList<>();
            JSONObject jsonObject = JSONObject.parseObject(cachedData);
            // 聚信立报告响应数据
            Object responseData = jsonObject.get("data");
            JSONObject data = null;
            if (responseData instanceof String) {
                String dataJson = (String) responseData;
                data = JSONObject.parseObject(dataJson);
            } else if (responseData instanceof JSONObject) {
                data = (JSONObject) responseData;
            }
            if (data == null) {
                response.setCode(DHB_ERROR_CODE);
                response.setMsg("聚信立原始数据data节点不存在");
                return response;
            }
            Object object = JSONPath.eval(data, "$.raw_data.members.transactions");
            if (object == null) {
                response.setCode(DHB_ERROR_CODE);
                response.setMsg("聚信立原始数据transactions节点不存在");
                return response;
            }
            if (object instanceof JSONArray) {
                JSONArray transactions = (JSONArray) object;
                for (int i = 0, size = transactions.size(); i < size; i++) {
                    JSONObject ele = transactions.getJSONObject(i);
                    List<CallLogEntity> list = fillCallLogList(ele);
                    if (CollectionUtils.isNotEmpty(list)) {
                        callLogList.addAll(list);
                    }
                }
            } else if (object instanceof JSONObject) {
                JSONObject transaction = (JSONObject) object;
                List<CallLogEntity> list = fillCallLogList(transaction);
                if (CollectionUtils.isNotEmpty(list)) {
                    callLogList.addAll(list);
                }
            }
            response.setData(callLogList);
            response.setCode(DHB_OK_CODE);
            return response;
        } catch (Exception e) {
            LOG.error("从聚信立报告中获取用户通话详情出错,name:{},mobile:{},idCard:{},error:{}", request.getName(), request.getMobile(), request.getIdCard(), e);
            response.setCode(DHB_ERROR_CODE);
            response.setMsg(e.getMessage());
            return response;
        }
    }


    private List<CallLogEntity> fillCallLogList(JSONObject transaction) {
        List<CallLogEntity> callLogEntityList = new ArrayList<>();
        JSONArray calls = transaction.getJSONArray("calls");
        if (calls == null) {
            return callLogEntityList;
        }
        //20 - 2000
        for (int j = 0; j < calls.size(); j++) {
            CallLogEntity callLogEntity = new CallLogEntity();
            JSONObject jsonObject = calls.getJSONObject(j);
            callLogEntity.setCall_tel(jsonObject.getString("other_cell_phone"));
            if (!MobileUtil.isMobile(callLogEntity.getCall_tel())) {
                continue;
            }
            callLogEntity.setCall_duration(jsonObject.getFloat("use_time"));
            String startTime = jsonObject.getString("start_time");
            if(StringUtils.isNotEmpty(startTime)) {
                callLogEntity.setCall_time(DateUtils.strToDate(startTime).getTime());
            }
            String initType = jsonObject.getString("init_type");
            if ("被叫".equals(initType)) {
                callLogEntity.setCall_method(2L);
            } else if ("主叫".equals(initType)) {
                callLogEntity.setCall_method(1L);
            }
            callLogEntityList.add(callLogEntity);
        }
        return callLogEntityList;
    }


    @Override
    public void saveRequestHistory(DianHuaBangCallback dianHuaBangCallback) {
        dianHuaBangCallbackMapper.insertSelective(dianHuaBangCallback);
    }

    @Override
    public DianHuaBangCallback getDianHuaBangCallbackBySid(String sid) {
        DianHuaBangCallbackExample example = new DianHuaBangCallbackExample();
        DianHuaBangCallbackExample.Criteria criteria = example.createCriteria();
        criteria.andSidEqualTo(sid);
        criteria.andStatusEqualTo((byte) 1);
        //注意请求参数需要获取
        List<DianHuaBangCallback> list = dianHuaBangCallbackMapper.selectByExampleWithBLOBs(example);
        if (CollectionUtils.isEmpty(list) || list.size() != 1) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public int updateRequestHistory(DianHuaBangCallback dianHuaBangCallback) {
        if (dianHuaBangCallback == null || StringUtils.isEmpty(dianHuaBangCallback.getSid())) {
            return -1;
        }
        DianHuaBangCallbackExample example = new DianHuaBangCallbackExample();
        DianHuaBangCallbackExample.Criteria criteria = example.createCriteria();
        criteria.andSidEqualTo(dianHuaBangCallback.getSid());
        return dianHuaBangCallbackMapper.updateByExampleSelective(dianHuaBangCallback, example);
    }

    @Override
    public String signUrl(String url, Map<String, Object> signature) {
        if (StringUtils.isEmpty(url)) {
            throw new ServiceException("url is empty");
        }
        int index = url.lastIndexOf("?");
        url = index < 0 ? url + "?" : url;
        StringBuilder sb = new StringBuilder(url);
        for (Map.Entry<String, Object> entry : signature.entrySet()) {
            sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
        }
        url = sb.toString();
        index = url.lastIndexOf("&");
        url = url.substring(0, index);
        return url;
    }

    @Override
    public Map<String, Object> signature(String apikey, String appsecret, Integer nonce, Long timestamp) {
        if (StringUtils.isEmpty(apikey)) {
            LOG.error("illegal parameter apiKey");
            throw new ServiceException("1101", "illegal parameter apiKey");
        }
        if (StringUtils.isEmpty(appsecret)) {
            LOG.error(" invalid parameter appSecret");
            throw new ServiceException("1102", "invalid parameter appSecret");
        }
        Map<String, Object> params = new HashMap<>(8);
        nonce = checkOnece(nonce);
        timestamp = checkTimestamp(timestamp);
        ArrayList<String> list = new ArrayList<>();
        list.add(String.valueOf(timestamp));
        list.add(apikey);
        list.add(appsecret);
        list.add(String.valueOf(nonce));
        Collections.sort(list);
        String signature = DigestUtils.shaHex(list.get(0) + list.get(1) + list.get(2) + list.get(3));
        params.put("timestamp", timestamp);
        params.put("nonce", nonce);
        params.put("apikey", apikey);
        params.put("signature", signature);
        params.put("pids", "105");
        return params;
    }

    @Override
    public DianHuaBangResponseEntity cuishou(String url, String params) {
        if (StringUtils.isEmpty(url)) {
            return DianHuaBangResponseEntity.fail("-1", "url不合法");
        }
        CloseableHttpResponse response = null;
        try {
            CloseableHttpClient httpClient = HttpClientFactory.getHttpClient();
            HttpPost httPost = new HttpPost(url);
            httPost.setHeader("Content-Encoding", "gzip");
            httPost.addHeader("Content-type", "application/json; charset=ISO-8859-1");
            httPost.setEntity(new StringEntity(GZipUtil.compress(params)));
            response = httpClient.execute(httPost);
            //响应
            String body = EntityUtils.toString(response.getEntity(), "utf-8");
            JSONObject jsonObject = JSONObject.parseObject(body);
            String status = jsonObject.getString("status");
            String msg = jsonObject.getString("msg");
            Object object = jsonObject.get("data");
            return new DianHuaBangResponseEntity(status, msg, object);
        } catch (Exception e) {
            LOG.error("请求出错:{}", e);
            return DianHuaBangResponseEntity.fail("-1", e.getMessage());
        } finally {
            if (response != null) {
                //如果使用CloseableHttpResponse.close来释放链接，它将直接关闭socket，导致长连接不可用。
                //可以使用EntityUtils.consume()或者EntityUtils.toString方法消费响应体
                try {
                    response.close();
                } catch (IOException e) {
                    LOG.error("关闭链接失败:{}", e);
                }
            }
        }
    }


    /**
     * 1000-9999之间
     *
     * @param once
     */
    private Integer checkOnece(Integer once) {
        Integer res = once;
        if (res != null) {
            if (res < 1000 || res > 9999) {
                res = RandomUtils.nextInt(1000, 9999);
            }
        } else {
            res = RandomUtils.nextInt(1000, 9999);
        }
        return res;
    }

    /**
     * 校验时间戳
     *
     * @param timestamp
     * @return
     */
    private Long checkTimestamp(Long timestamp) {
        if (timestamp != null) {
            return TimestampUtil.getOffsetTimestamp(timestamp, 10);
        } else {
            return DateUtil.getTimestamp(new Date(), 10);
        }
    }
}
